Inside Macintosh: Sound

| Previous | Chapter contents | Chapter top | Section top | Next |

Playing Notes

You can play notes one at a time by using the SndDoCommand or SndDoImmediate function to issue freqDurationCmd sound commands. A sound plays for a specified duration at a specified frequency. You can play sounds defined by any of the three sound data formats. If you play wave-table data or sampled-sound data, then a voice must previously have been installed in the channel. (See "Installing Voices Into Channels" for instructions on installing wave tables and sampled sounds as voices.)

You can also play notes by issuing the freqCmd command, which is identical to the  freqDurationCmd command, except that no duration is specified when you issue  freqCmd .

A freqDurationCmd command might in certain cases continue playing until another command is available in the sound channel. Therefore, to play a single note for a specified duration, you should issue freqDurationCmd followed immediately by quietCmd . See  "Stopping Sound Channels" for further details on  quietCmd .

The structure of a freqDurationCmd command is slightly different from that of most other sound commands. The param1 field contains the duration of the sound, specified in half-milliseconds. A value of 2000 represents a duration of 1 second. The maximum duration is 32,767, or about 16 seconds, in Sound Manager versions 2.0 and earlier; the maximum duration in Sound Manager version 3.0 and later is 65,536, or about 32 seconds. The param2 field specifies the frequency of the sound. The frequency is specified as a MIDI note value (that is, a value defined by the established MIDI standard). Listing 1-25 uses the freqDurationCmd command in a way that ensures the sound stops after the specified duration.

Listing 25 Using the freqDurationCmd command

PROCEDURE MyPlayFrequencyOnce (mySndChan: SndChannelPtr;
                                            myMIDIValue: Integer;
                                            milliseconds: Integer);
CONST
    kNoWait = TRUE;                             {add now to full queue?}
VAR
    mySndCmd:       SndCommand;                 {a sound command}
    myErr:          OSErr;
BEGIN
    {Start the sound playing.}
    WITH mySndCmd DO
    BEGIN
        cmd := freqDurationCmd;                 {play for period of time}
        param1 := milliseconds * 2;             {half-milliseconds}
        param2 := myMIDIValue;                  {MIDI value to play}
    END;
    myErr := SndDoCommand(mySndChan, mySndCmd, NOT kNoWait);
    IF myErr <> noErr THEN
        DoError(myErr)
    ELSE
    BEGIN                                       {ensure that sound stops}
        WITH mySndCmd DO
        BEGIN
            cmd := quietCmd;                    {stop playing sound}
            param1 := 0;                        {unused with quietCmd}
            param2 := 0;                        {unused with quietCmd}
        END;
        myErr := SndDoCommand(mySndChan, mySndCmd, NOT kNoWait);
        IF myErr <> noErr THEN
            DoError(myErr);
    END;
END;

Table 1-3 shows the decimal values that can be sent with a freqDurationCmd or freqCmd command. Middle C is represented by a value of 60 and is defined by a special Sound Manager constant.

CONST
    kMiddleC            = 60;           {MIDI note value for middle C}

Other specifiable frequencies correspond to MIDI note values.

Table 3 Frequencies expressed as MIDI note values

 

A

A#

B

C

C#

D

D#

E

F

F#

G

G#

Octave 1

 

 

 

0

1

2

3

4

5

6

7

8

Octave 2

9

10

11

12

13

14

15

16

17

18

19

20

Octave 3

21

22

23

24

25

26

27

28

29

30

31

32

Octave 4

33

34

35

36

37

38

39

40

41

42

43

44

Octave 5

45

46

47

48

49

50

51

52

53

54

55

56

Octave 6

57

58

59

60

61

62

63

64

65

66

67

68

Octave 7

69

70

71

72

73

74

75

76

77

78

79

80

Octave 8

81

82

83

84

85

86

87

88

89

90

91

92

Octave 9

93

94

95

96

97

98

99

100

101

102

103

104

Octave 10

105

106

107

108

109

110

111

112

113

114

115

116

Octave 11

117

118

119

120

121

122

123

124

125

126

127

 

You can play square-wave and wave-table data at these frequencies only. If you are playing a sampled sound, however, you can modify the sampleRate field of the sound header to play a sound at an arbitrary frequency. To do so, use the following formula:

new sample rate = (new frequency / original frequency) * original sample rate

where the new and original frequencies are measured in hertz. To convert a MIDI value to hertz for use in this formula, note that middle C is defined as 261.625 Hz and that the ratio between the frequencies of consecutive MIDI values equals the twelfth root of 2, defined by the constant twelfthRootTwo .

CONST
    twelfthRootTwo                  = 1.05946309434;

When calculating with numbers of type Fixed , pay attention to possible overflows. The maximum value of a number of type Fixed is 65,535.0. As a result, some sample rates and pitches cannot be specified. Sound Manager version 3.0 fixes these overflow problems.

You can rest a channel for a specified duration by issuing a restCmd command. The duration, specified in half-milliseconds, is passed in the param1 field of the sound command.

Installing Voices Into Channels

Looping a Sound Indefinitely


© 1998 Apple Computer, Inc.

| Previous | Chapter contents | Chapter top | Section top | Next |